package com.peppa.common.grayconfig.Strategy;

import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;
import com.peppa.common.grayconfig.Strategy.factory.AnnoStrategy;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.netflix.ribbon.eureka.EurekaServerIntrospector;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Random;

/**
 * dev环境自动策略
 * 按照eureka的metadata里的ver=dev来选择路由
 */
@AnnoStrategy
public class AutoDevStrategy extends StrategyAbstract {
    @Value("${podenv:}")
    private String podenv;

    public AutoDevStrategy() {
        setName(A_DEV);
        setOrder(SORT_A_DEV);
    }

    @Override
    public Server getServer(ILoadBalancer balancer){
        try {
            EurekaServerIntrospector serverIntrospector = new EurekaServerIntrospector();
            Server serverRet = null;
            int count = 0;

            while(true) {
                if (serverRet == null && count++ < 5) {
                    List<Server> servers = balancer.getAllServers();
                    List<Server> serversReach = balancer.getReachableServers();
                    if (serversReach.size() == 0 || servers.size()==0){
                        return null;
                    }
                    //按照eureka的metadata里的ver=dev来选择
                    List<Server> devlist = new ArrayList<>();
                    for (Server server : servers) {
                        Map metadata = serverIntrospector.getMetadata(server);
                        String verkey = "ver";
                        if (metadata.containsKey(verkey)) {
                            String value = (String) metadata.get(verkey);
                            if (value.equals("no"))
                                continue;
                            //服务器环境变量和要调用服务器的eureka中的环境变量相同，则说明是同一环境，可以调用
                            if (podenv.equals(value)) {
                                devlist.add(server);
                                continue;
                            }
                            if (value.equals("dev")) {
                                devlist.add(server);
                            }
                        }
                    }
                    if (devlist.size()==0)
                        return null;
                    serverRet = getRandom(devlist);
                    if (serverRet == null) {
                        Thread.yield();
                    } else {
                        if (serverRet.isAlive() && serverRet.isReadyToServe()) {
                            return serverRet;
                        }
                    }
                    serverRet = null;
                    continue;
                }
                if (count >= 5) {
                    logger.warn("No available alive servers after 5 tries from load balancer: " + balancer);
                }

                return serverRet;
            }
        }catch (Exception e){
            logger.error("ver选择异常",e.getMessage());
        }
        return null;
    }
    @Override
    public String getName(){
        return name;
    }
}
